{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# numpy处理数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Prerequisites"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 生成序列\n",
    "\n",
    "使用numpy生成等差数列有两种方式：\n",
    "\n",
    "方式一：使用`np.arange(start, stop, step)`，这种方式便于生成元素之差为step的数组\n",
    "\n",
    "方式二：使用`np.linspace(start, stop, num)`，这种方式便于生成元素个数为num的数组，还可以通过endpoint参数指定元素是否包含端点。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The endpoints of A:0.0,2.9000000000000004\n",
      "The endpoints of B:0.0,3.0\n"
     ]
    }
   ],
   "source": [
    "A = np.arange(0, 3, 0.1)  # 数据的间距为0.1\n",
    "B = np.linspace(0, 3, 30, endpoint=True) # 生成30个元素，包含端点0和3，默认包含\n",
    "\n",
    "print(f'The endpoints of A:{A[0]},{A[-1]}')\n",
    "print(f'The endpoints of B:{B[0]},{B[-1]}')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## numpy数组\n",
    "\n",
    "**`np.ndarray`类和`np.array`函数**\n",
    "\n",
    "由`np.array`生成的数组是np.ndarray类的实例，可以用`isinstance(a, np.ndarray)`进行验证。\n",
    "\n",
    "数组的生成有很多种方式，例如`array、linspace、arange、full、eye、emptys、ones、zeros`，比较常用的是前五个：`array、linspace、arange、full、eye`，其中full可以使数组填充给定值，eye生成单位矩阵。\n",
    "\n",
    "empty和ones的区别：empty和ones都生成指定shape的数组，但是empty不进行初始化，ones将数组初始化为0。\n",
    "\n",
    "例子如下：\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "E:\n",
      "[[5 3 4]\n",
      " [5 3 4]\n",
      " [5 3 4]\n",
      " [5 3 4]\n",
      " [5 3 4]]\n"
     ]
    }
   ],
   "source": [
    "# numpy数组\n",
    "\n",
    "A = np.array([1,2,3,3,4])\n",
    "B = np.linspace(1, 12, 9)\n",
    "C = np.arange(1, 12, 2)\n",
    "\n",
    "# full填充\n",
    "D = np.full((3,4), 9)\n",
    "# 生成五行数组，每行数组都是[5,3,4]\n",
    "E = np.full((5,3), [5,3,4])\n",
    "print(f'E:\\n{E}')\n",
    "\n",
    "# 单位矩阵\n",
    "F = np.eye(4)\n",
    "\n",
    "# ones、zeros可以用full来代替"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2239416229200\n",
      "2239381295824\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "a = np.reshape(np.arange(1,13),(3,4))\n",
    "b = np.reshape(np.arange(2,14),(4,3))\n",
    "print(id(a))\n",
    "print(id(a*2))\n",
    "isinstance(a, np.ndarray)\n",
    "isinstance(np.array_repr, np.ndarray)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 矩阵乘法\n",
    "矩阵乘法可以有四种操作，数乘、点乘、元素积(elementwise)、Kronecker积，但当前阶段只需要用到前三种，第四种先不管。\n",
    "\n",
    "数乘即将一个数与矩阵中的各个数相乘，numpy中使用`*`来完成数乘（`*`运算也用来进行元素积）：\n",
    "\\begin{align*}\n",
    "A*2=\n",
    "\\begin{pmatrix}\n",
    " 1 &  2 &  3 &  4 \\\\\n",
    " 5 &  6 &  7 &  8 \\\\\n",
    " 9 & 10 & 11 & 12\n",
    "\\end{pmatrix}\n",
    "*2 = \n",
    "\\begin{pmatrix}\n",
    " 1*2 &  2*2 &  3*2 &  4*2 \\\\\n",
    " 5*2 &  6*2 &  7*2 &  8*2 \\\\\n",
    " 9*2 & 10*2 & 11*2 & 12*2\n",
    "\\end{pmatrix}\n",
    "\\end{align*}\n",
    "注意A*2的行列式计算:$|A*2| = 2^3|A|$\n",
    "\n",
    "\n",
    "矩阵点乘即线性代数中所介绍的矩阵乘法，AB要求A的列数等于B的行数，在numpy中使用`np.dot(A,B)`来完成矩阵乘法，或者使用`@`运算符，`A @ B`\n",
    "\n",
    "矩阵元素积(elementwise)是指将两个矩阵中相同位置的元素对应相乘，这要求连个矩阵的shape相同，在numpy中用`*`来完成矩阵乘法，`*`运算也用来完成数乘\n",
    "\n",
    "注意，`*`运算会产生一个新的数组（数乘和元素积都会产生新数组），可以用id()函数进行检验。\n",
    "\n",
    "如果不想产生新数组，可以使用运算符`*=、+=`等运算符。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "矩阵A和B\n",
      "A:[[1 2 3]\n",
      " [4 5 6]]\n",
      "B:[[2 3]\n",
      " [4 5]\n",
      " [6 7]]\n",
      "*运算符生成新数组，导致A和A*2的id不同\n",
      "id of A:2239416229392\n",
      "id of A*2:2239416294448\n",
      "用@进行点积运算\n",
      "D:[[28 34]\n",
      " [64 79]]\n",
      "用*进行elementwise\n",
      "A*A：[[ 1  4  9]\n",
      " [16 25 36]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "A = np.reshape(np.arange(1,7), (2, 3))\n",
    "B = np.reshape(np.arange(2,8), (3, 2))\n",
    "print('矩阵A和B')\n",
    "print(f'A:{A}\\nB:{B}')\n",
    "# 数乘\n",
    "C = A*2\n",
    "print('*运算符生成新数组，导致A和A*2的id不同')\n",
    "print(f'id of A:{id(A)}\\nid of A*2:{id(C)}')\n",
    "\n",
    "# 点积，即矩阵乘法\n",
    "D = A@B  # 或者np.dot(A, B)\n",
    "print('用@进行点积运算')\n",
    "print(f'D:{D}')\n",
    "\n",
    "# 元素积，elementwise，矩阵的shape需要一致\n",
    "E = A*A\n",
    "print('用*进行元素积（elementwise）')\n",
    "print(f'A*A：{E}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 维度操作（轴操作）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on built-in function array in module numpy:\n",
      "\n",
      "array(...)\n",
      "    array(object, dtype=None, *, copy=True, order='K', subok=False, ndmin=0,\n",
      "          like=None)\n",
      "    \n",
      "    Create an array.\n",
      "    \n",
      "    Parameters\n",
      "    ----------\n",
      "    object : array_like\n",
      "        An array, any object exposing the array interface, an object whose\n",
      "        __array__ method returns an array, or any (nested) sequence.\n",
      "    dtype : data-type, optional\n",
      "        The desired data-type for the array.  If not given, then the type will\n",
      "        be determined as the minimum type required to hold the objects in the\n",
      "        sequence.\n",
      "    copy : bool, optional\n",
      "        If true (default), then the object is copied.  Otherwise, a copy will\n",
      "        only be made if __array__ returns a copy, if obj is a nested sequence,\n",
      "        or if a copy is needed to satisfy any of the other requirements\n",
      "        (`dtype`, `order`, etc.).\n",
      "    order : {'K', 'A', 'C', 'F'}, optional\n",
      "        Specify the memory layout of the array. If object is not an array, the\n",
      "        newly created array will be in C order (row major) unless 'F' is\n",
      "        specified, in which case it will be in Fortran order (column major).\n",
      "        If object is an array the following holds.\n",
      "    \n",
      "        ===== ========= ===================================================\n",
      "        order  no copy                     copy=True\n",
      "        ===== ========= ===================================================\n",
      "        'K'   unchanged F & C order preserved, otherwise most similar order\n",
      "        'A'   unchanged F order if input is F and not C, otherwise C order\n",
      "        'C'   C order   C order\n",
      "        'F'   F order   F order\n",
      "        ===== ========= ===================================================\n",
      "    \n",
      "        When ``copy=False`` and a copy is made for other reasons, the result is\n",
      "        the same as if ``copy=True``, with some exceptions for 'A', see the\n",
      "        Notes section. The default order is 'K'.\n",
      "    subok : bool, optional\n",
      "        If True, then sub-classes will be passed-through, otherwise\n",
      "        the returned array will be forced to be a base-class array (default).\n",
      "    ndmin : int, optional\n",
      "        Specifies the minimum number of dimensions that the resulting\n",
      "        array should have.  Ones will be pre-pended to the shape as\n",
      "        needed to meet this requirement.\n",
      "    like : array_like\n",
      "        Reference object to allow the creation of arrays which are not\n",
      "        NumPy arrays. If an array-like passed in as ``like`` supports\n",
      "        the ``__array_function__`` protocol, the result will be defined\n",
      "        by it. In this case, it ensures the creation of an array object\n",
      "        compatible with that passed in via this argument.\n",
      "    \n",
      "        .. versionadded:: 1.20.0\n",
      "    \n",
      "    Returns\n",
      "    -------\n",
      "    out : ndarray\n",
      "        An array object satisfying the specified requirements.\n",
      "    \n",
      "    See Also\n",
      "    --------\n",
      "    empty_like : Return an empty array with shape and type of input.\n",
      "    ones_like : Return an array of ones with shape and type of input.\n",
      "    zeros_like : Return an array of zeros with shape and type of input.\n",
      "    full_like : Return a new array with shape of input filled with value.\n",
      "    empty : Return a new uninitialized array.\n",
      "    ones : Return a new array setting values to one.\n",
      "    zeros : Return a new array setting values to zero.\n",
      "    full : Return a new array of given shape filled with value.\n",
      "    \n",
      "    \n",
      "    Notes\n",
      "    -----\n",
      "    When order is 'A' and `object` is an array in neither 'C' nor 'F' order,\n",
      "    and a copy is forced by a change in dtype, then the order of the result is\n",
      "    not necessarily 'C' as expected. This is likely a bug.\n",
      "    \n",
      "    Examples\n",
      "    --------\n",
      "    >>> np.array([1, 2, 3])\n",
      "    array([1, 2, 3])\n",
      "    \n",
      "    Upcasting:\n",
      "    \n",
      "    >>> np.array([1, 2, 3.0])\n",
      "    array([ 1.,  2.,  3.])\n",
      "    \n",
      "    More than one dimension:\n",
      "    \n",
      "    >>> np.array([[1, 2], [3, 4]])\n",
      "    array([[1, 2],\n",
      "           [3, 4]])\n",
      "    \n",
      "    Minimum dimensions 2:\n",
      "    \n",
      "    >>> np.array([1, 2, 3], ndmin=2)\n",
      "    array([[1, 2, 3]])\n",
      "    \n",
      "    Type provided:\n",
      "    \n",
      "    >>> np.array([1, 2, 3], dtype=complex)\n",
      "    array([ 1.+0.j,  2.+0.j,  3.+0.j])\n",
      "    \n",
      "    Data-type consisting of more than one element:\n",
      "    \n",
      "    >>> x = np.array([(1,2),(3,4)],dtype=[('a','<i4'),('b','<i4')])\n",
      "    >>> x['a']\n",
      "    array([1, 3])\n",
      "    \n",
      "    Creating an array from sub-classes:\n",
      "    \n",
      "    >>> np.array(np.mat('1 2; 3 4'))\n",
      "    array([[1, 2],\n",
      "           [3, 4]])\n",
      "    \n",
      "    >>> np.array(np.mat('1 2; 3 4'), subok=True)\n",
      "    matrix([[1, 2],\n",
      "            [3, 4]])\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(np.ndarray)\n",
    "help(np.array)"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "a17d8fbc39f154724391315e19256412600de31bba27aef41cfe960effe5852b"
  },
  "kernelspec": {
   "display_name": "Python 3.9.7 ('SciencePy')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
